<template>
  <div class="l-rblock l-tab-page view-page">
    <l-layout class="l-tab-page" :bottom="300" :top="44" :topMove="false">
      <template #top>
        <div class="top-panel">
          <div>
            <el-tooltip
              :content="$t('查询')"
              :enterable="false"
              placement="bottom"
              ><el-button
                class="learun-text-btn"
                type="text"
                icon="learun-icon-play-base"
                :loading="tableLoading"
                @click="loadTableData"
              />
            </el-tooltip>
          </div>

          <div class="right-btn">
            <el-tooltip
              :content="openCodeInfo ? $t('关闭说明') : $t('查看说明')"
              :enterable="false"
              placement="bottom"
              ><el-button
                class="learun-text-btn"
                type="text"
                :icon="
                  openCodeInfo
                    ? 'learun-icon-double-right'
                    : 'learun-icon-circle-question'
                "
                @click="openCodeInfo = !openCodeInfo"
              />
            </el-tooltip>
          </div>
        </div>
      </template>
      <l-layout :right="360">
        <l-code-mirror
          v-model="currentConfig.sql"
          mode="application/javascript"
        ></l-code-mirror>
        <template #right>
          <l-code-mirror v-if="openCodeInfo" readOnly v-model="tempCode">
          </l-code-mirror>
        </template>
      </l-layout>

      <template #bottom>
        <div v-if="columns.length > 0" class="l-rblock">
          <l-table
            ref="mainTable"
            :columns="columns"
            :dataSource="tableData"
            :loading="tableLoading"
            :isPage="true"
            :pageTotal="tableTotal"
            :tablePage.sync="tableCurrentPage"
            @loadPageData="turnTablePage"
          >
          </l-table>
        </div>
      </template>
    </l-layout>
    <div :class="['info-wraper', { opened: infoWraperOpen }]">
      <el-form
        v-show="infoWraperOpenType == 'info'"
        style="padding: 10px 10px 0 10px"
        :model="formData"
        :rules="rules"
        size="mini"
        ref="form"
      >
        <el-form-item :label="$t('名称')" prop="f_Name">
          <el-input
            v-model="formData.f_Name"
            :placeholder="$t('请输入')"
          ></el-input>
        </el-form-item>
        <el-form-item :label="$t('编码')" prop="f_Code">
          <el-input
            v-model="formData.f_Code"
            :placeholder="$t('请输入')"
          ></el-input>
        </el-form-item>
        <el-form-item :label="$t('分类')" prop="f_Category">
          <l-tree-select
            v-model="formData.f_Category"
            :options="lr_dataItemTree(lr_dataItem['datasourceType'])"
          />
        </el-form-item>
        <el-form-item :label="$t('备注')" prop="f_Description">
          <el-input
            type="textarea"
            v-model="formData.f_Description"
            rows="6"
          ></el-input>
        </el-form-item>
      </el-form>
      <template v-if="infoWraperOpenType == 'inputParams'">
        <div v-if="inputDbSource.length > 0" style="padding: 10px">
          <div style="margin-bottom: 8px">
            <el-button type="primary" size="mini" @click="handleAddDbsource">{{
              $t("添加输入数据源")
            }}</el-button>
          </div>
          <div
            class="field-row"
            v-for="(item, index) in inputDbSource"
            :key="item.code"
          >
            <div :class="['field-row-header', getdbSourceClass(item)]">
              {{ getdbSourceTypeName(item) }}
            </div>
            <div class="field-row-content">{{ getdbSourceName(item) }}</div>
            <el-button
              :title="$t('删除')"
              @click="handleRemoveDbsource(index)"
              class="learun-row-form-input-delete"
              circle
              plain
              size="mini"
              type="danger"
            >
              <i class="el-icon-close"></i>
            </el-button>
          </div>
        </div>

        <div v-else class="learun-empty">
          <el-empty :description="$t('还没有添加输入数据源')" />
          <el-button type="primary" size="mini" @click="handleAddDbsource">{{
            $t("添加一个")
          }}</el-button>
        </div>
      </template>
      <template v-else-if="infoWraperOpenType == 'order'">
        <el-form
          style="padding: 10px 10px 0 10px"
          size="mini"
          v-if="orders.length > 0"
        >
          <div
            class="learun-row-form-input"
            :key="index"
            v-for="(item, index) in orders"
          >
            <el-form-item :label="$t('字段')" style="margin-bottom: 8px">
              <el-autocomplete
                v-model="item.field"
                :fetch-suggestions="querySearchAsync"
              ></el-autocomplete>
            </el-form-item>

            <el-form-item :label="$t('倒序')" style="margin-bottom: 8px">
              <el-switch v-model="item.isDESC"></el-switch>
            </el-form-item>
            <el-button
              :title="$t('删除')"
              @click="handleRemoveOrder(index)"
              class="learun-row-form-input-delete"
              circle
              plain
              size="mini"
              type="danger"
            >
              <i class="el-icon-close"></i>
            </el-button>
          </div>
        </el-form>
        <div v-if="orders.length > 0" class="mt-8" style="padding-left: 10px">
          <el-button type="primary" size="mini" @click="handleAddOrder">{{
            $t("添加排序字段")
          }}</el-button>
        </div>
        <div v-else class="learun-empty">
          <el-empty :description="$t('还没有添加排序字段')" />
          <el-button type="primary" size="mini" @click="handleAddOrder">{{
            $t("添加一个")
          }}</el-button>
        </div>
      </template>
      <template v-else-if="infoWraperOpenType == 'field'">
        <div v-if="columns.length > 0" style="padding: 10px">
          <div class="field-row" v-for="field in columns" :key="field.prop">
            <div :class="['field-row-header', getTypeClass(field)]">
              {{ getTypeName(field) }}
            </div>
            <div class="field-row-content">{{ getColNames(field) }}</div>
          </div>
        </div>
        <div v-else class="learun-empty">
          <el-empty :description="$t('暂无字段信息,请在左侧写入脚本并查询')" />
        </div>
      </template>
    </div>
    <div class="right-side">
      <div
        :class="['vertical-btn', { opened: infoWraperOpenType == 'info' }]"
        @click="handleClickRightSideBtn('info')"
      >
        {{ $t('基础信息') }}
      </div>
      <div
        :class="[
          'vertical-btn',
          { opened: infoWraperOpenType == 'inputParams' },
        ]"
        @click="handleClickRightSideBtn('inputParams')"
      >
        {{ $t('输入数据源') }}
      </div>
      <div
        :class="['vertical-btn', { opened: infoWraperOpenType == 'order' }]"
        @click="handleClickRightSideBtn('order')"
      >
        {{ $t('排序字段') }}
      </div>
      <div
        :class="['vertical-btn', { opened: infoWraperOpenType == 'field' }]"
        @click="handleClickRightSideBtn('field')"
      >
        {{ $t('字段信息') }}
      </div>
    </div>

    <l-dbsource-selectdialog
      :visible.sync="dbsourceSelectdialog"
      @select="dbsourceSelect"
    />
  </div>
</template>
<script>
const api = window.$api.data.dbsource;
export default {
  data() {
    return {
      infoWraperOpen: true,
      infoWraperOpenType: "info",
      dbsourceSelectdialog: false,

      openCodeInfo: false,

      tempCode: `
// 获取当前登录用户ID
learun.userId

// 获取当前登录用户账号
learun.userAccount

// 获取当前登录用户公司ID
learun.companyId

// 获取当前登录用户部门ID
learun.departmentId 

// 获取外部输入参数
// 数据及联使用
learun.param 

// 获取输入数据源数据
// 注:需要在右侧输入数据源处先添加
var list = learun.data['数据源编码']

// 返回结果
return list


`,

      formData: {
        f_Name: "",
        f_Code: "",
        f_Category: "",
        f_Description: "",
      },
      rules: {
        f_Name: [{ required: true, message: "请输入" }],
        f_Category: [{ required: true, message: "请选择" }],
        f_Code: [
          { required: true, message: "请输入" },
          {
            validator: this.lr_existDbFiled,
            keyValue: () => {
              return this.formData.f_Id;
            },
            tableName: "lr_base_datasource",
            keyName: "f_Id",
            trigger: "null",
          },
        ],
      },

      currentConfig: {
        sql: "",
      },

      orders: [],
      columns: [],
      inputDbSource: [],

      tableData: [],

      tableLoading: false,
      tableTotal: 0,
      tablePageSize: 50,
      tableCurrentPage: 1,
    };
  },
  created() {
    this.lr_loadDblink();
  },
  computed: {},
  methods: {
    handleClickRightSideBtn(type) {
      if (this.infoWraperOpenType != type) {
        this.infoWraperOpenType = type;
        this.infoWraperOpen = true;
      } else {
        this.infoWraperOpenType = "";
        this.infoWraperOpen = false;
      }
    },

    async loadTableData(isNotFirst) {
      const { sql } = this.currentConfig;

      if (!sql) {
        this.$message({
          type: "error",
          message: this.$t(`请填写脚本`),
        });
        return;
      }

      if (!isNotFirst) {
        this.tableCurrentPage = 1;
      }
      this.tableLoading = true;
      let queryData = {
        rows: this.tablePageSize,
        page: this.tableCurrentPage,
      };

      const res = await this.$awaitWraper(
        api.getViewPageByEntity(queryData, {
          f_DbId: "learun_view",
          f_Sql: this.getSettingJson(),
        })
      );
      if (res) {
        this.setColumns(res.cols);
        this.tableData = res.rows;
        this.tableTotal = res.records;
      } else {
        this.setColumns([]);
        this.tableData = [];
        this.tableTotal = [];
      }

      this.tableLoading = false;
    },
    turnTablePage({ rows }) {
      this.tablePageSize = rows;
      this.loadTableData(true);
    },

    setColumns(columns) {
      this.columns = columns;
      this.$refs.mainTable && this.$refs.mainTable.doLayout();
    },

    getSettingJson() {
      const { sql } = this.currentConfig;
      const settingJson = {
        orders: this.$deepClone(this.orders),
        type: "code",
        dataSourceInputs: this.inputDbSource,
        sqls: [
          {
            sql,
          },
        ],
        columns: this.columns.map((t) => ({
          prop: t.prop,
          label: t.label,
          csType: t.csType,
        })),
      };
      return this.lr_AESEncrypt(JSON.stringify(settingJson), "learun");
    },

    /**排序字段设置 */
    handleAddOrder() {
      this.orders.push({
        field: "",
        isDESC: false,
      });
    },
    handleRemoveOrder(index) {
      this.orders.splice(index, 1);
    },
    async querySearchAsync(queryString, cb) {
      const list = this.columns;
      const res = queryString
        ? list.filter(
            (t) =>
              t.prop.indexOf(queryString) != -1 ||
              t.label.indexOf(queryString) != -1
          )
        : list;
      cb(
        res.map((t) => {
          return { value: this.getColNames(t) };
        })
      );
    },

    /**获取字段信息*/
    getColNames({ prop, label }) {
      let name = prop;
      if (prop != label) {
        name = `${prop}(${label})`;
      }

      return name;
    },
    getTypeClass({ csType }) {
      switch (csType.toLowerCase()) {
        case "string":
        case "text":
          return "str";
        case "int":
        case "int64":
        case "int32":
        case "int16":
        case "long":
        case "short":
        case "decimal":
        case "double":
        case "float":
          return "num";
        case "datetime":
          return "date";
        case "bool":
          return "bool";
        default:
          return "";
      }
    },
    getTypeName({ csType }) {
      switch (csType.toLowerCase()) {
        case "string":
        case "text":
          return "字符";
        case "int":
        case "int64":
        case "int32":
        case "int16":
        case "long":
        case "short":
        case "decimal":
        case "double":
        case "float":
          return "数字";
        case "datetime":
          return "日期";
        case "bool":
          return "布尔";
        default:
          return csType;
      }
    },

    /**输入数据源 */
    handleAddDbsource() {
      this.dbsourceSelectdialog = true;
    },
    async dbsourceSelect(list) {
      list.forEach(({ f_Code, f_Name, f_Type }) => {
        var oldItem = this.inputDbSource.find((t) => t.code == f_Code);
        if (oldItem) {
          oldItem.code = f_Code;
          oldItem.f_Name = f_Name;
          oldItem.f_Type = f_Type;
        } else {
          this.inputDbSource.push({
            code: f_Code,
            name: f_Name,
            type: f_Type,
          });
        }
      });
    },
    handleRemoveDbsource(index) {
      this.inputDbSource.splice(index, 1);
    },
    getdbSourceClass({ type }) {
      switch (type) {
        case 1:
          return "num";
        case 2:
          return "date";
        default:
          return "str";
      }
    },
    getdbSourceTypeName({ type }) {
      switch (type) {
        case 1:
          return "表";
        case 2:
          return "JS";
        default:
          return "SQL";
      }
    },
    getdbSourceName({ code, name }) {
      return `${code}(${name})`;
    },

    resetForm() {
      this.formData.f_Id = "";
      this.currentConfig = { sql: "" };

      this.$formClear(this.$refs.form);

      this.infoWraperOpenType = "info";
      this.infoWraperOpen = true;

      this.orders = [];
      this.inputDbSource = [];

      this.tableData = [];
      this.columns = [];
      this.$refs.mainTable && this.$refs.mainTable.doLayout();
    },
    // 校验表单
    async validateForm() {
      let valid = await this.$formValidateWraper(this.$refs.form);
      if (valid) {
        if (this.orders.findIndex((t) => !t.field) > -1) {
          this.$message({
            type: "error",
            message: this.$t(`请完善排序字段设置`),
          });
          return false;
        }
        const { sql } = this.currentConfig;
        if (!sql) {
          this.$message({
            type: "error",
            message: this.$t(`请填写脚本`),
          });
          return false;
        }

        const res = await this.$awaitWraper(
          api.getViewPageByEntity(
            {
              rows: 1,
              page: 1,
            },
            {
              f_DbId: "learun_view",
              f_Sql: this.getSettingJson(),
            }
          )
        );

        if(!res){
          return false
        }

        this.columns = res.cols

        return true;
      }

      return false;
    },
    setForm(data) {
      this.formData = {
        f_Id: data.f_Id,
        f_Name: data.f_Name,
        f_Code: data.f_Code,
        f_Category: data.f_Category,
        f_Description: data.f_Description,
      };
      const { orders, sqls, columns, dataSourceInputs } = JSON.parse(
        data.f_Sql
      );
      this.orders = orders;
      this.columns = columns;
      this.inputDbSource = dataSourceInputs;
      const { sql } = sqls[0];
      this.currentConfig = { sql };
      this.loadTableData();
    },
    getForm() {
      const postData = {
        f_Name: this.formData.f_Name,
        f_Code: this.formData.f_Code,
        f_Category: this.formData.f_Category,
        f_Description: this.formData.f_Description,

        f_DbId: "learun_view",
        f_Type: 2, // js脚本视图
        f_Sql: this.getSettingJson(),
      };
      return postData;
    },
  },
};
</script>

<style lang="scss" scoped>
@import "@/core/styles/variables.scss";
.view-page {
  display: flex;
}
.right-side {
  position: relative;
  height: 100%;
  width: 32px;
  min-width: 32px;
  background-color: #fff;
  border-left: 1px solid $border-color-base;
  flex-grow: 2;
}
.vertical-btn {
  position: relative;
  color: $heading-color;
  padding: 4px;
  text-align: center;
  border-bottom: 1px solid $border-color-base;
  cursor: pointer;
  &:hover {
    color: $primary-color;
  }
  &.opened {
    color: $primary-color;
    &::after {
      content: "";
      height: 100%;
      width: 1px;
      background-color: #fff;
      position: absolute;
      top: 0;
      left: -1px;
    }
  }
}
.info-wraper {
  height: 100%;
  width: 0;
  transition: 0.3s all;
  background-color: #fff;
  flex-grow: 2;
  opacity: 0;
  overflow: auto;

  &.opened {
    width: 320px;
    min-width: 320px;
    border-left: 1px solid $border-color-base;
    opacity: 1;
  }
}
.top-panel {
  position: relative;
  height: 40px;
  width: 100%;
  background-color: #fff;
  border-bottom: 1px solid $border-color-split;

  display: flex;
  align-items: center;
  padding-left: 8px;

  &__item {
    width: 200px;
    margin-right: 8px;
  }
}

.field-row {
  position: relative;
  display: flex;
  height: 40px;
  box-shadow: 0 2px 4px 0 rgb(0 0 0 / 8%);

  margin-bottom: 8px;
  &:last-child {
    margin-bottom: 0;
  }

  &-header {
    width: 40px;
    min-width: 40px;
    height: 100%;
    line-height: 40px;
    text-align: center;
    background-color: $info-color;
    color: #fff;

    border-radius: 2px 0 0 2px;

    // 数字 ，日期， 布尔
    &.str {
      background-color: $primary-color;
    }
    &.num {
      background-color: $success-color;
    }
    &.date {
      background-color: $warning-color;
    }
    &.bool {
      background-color: $error-color;
    }
  }

  &-content {
    border: 1px solid $border-color-base;
    border-left: 0;
    width: 100%;
    height: 100%;
    line-height: 38px;
    padding-left: 8px;

    border-radius: 0 2px 2px 0;
  }

  .learun-row-form-input-delete {
    display: none;
  }

  &:hover {
    .learun-row-form-input-delete {
      display: block;
    }
  }
}

.right-btn {
  position: absolute;
  right: 0;
  top: 0;
  display: flex;
  align-items: center;
  padding-right: 8px;
  height: 100%;
}

.learun-empty {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  .el-empty {
    padding-top: 0;
  }
}
</style>